package com.zjw.forum.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjw.forum.common.ResultCode;
import com.zjw.forum.config.AppConfig;
import com.zjw.forum.model.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.crypto.SecretKey;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Slf4j
public class JWTUtil {
    private static final String KEY="65SXSDuBWwszPOkoAEJPkSkI3OD/iURwwZsgX6iPXFY=";
    private static final long Expiration=1000*60*60;//10min
    private static final Key keys=Keys.hmacShaKeyFor(Decoders.BASE64.decode(KEY));

    /**
     * 构造token
     * @param str 存放的key
     * @param user 对应的value值
     */
    public static String genToken(String str, User user){
        //将java对象序列化成JSON字符串存储
        Map<String,Object> map=new HashMap<>();
        ObjectMapper objectMapper=SpringContextHolder.getBean(ObjectMapper.class);
        try {
            String s = objectMapper.writeValueAsString(user);
            //存放负载信息
            map.put(str,s);
        } catch (JsonProcessingException e) {
            log.error("序列化失败");
            return null;
        }
        //根据keys生成令牌
        return Jwts.builder().signWith(keys).setClaims(map)
                .setExpiration(new Date(System.currentTimeMillis()+Expiration))
                .compact();
    }

    /**
     * 生成随机字符串
     * @return
     */
    private static String genKey(){
        SecretKey secretKey=Keys.secretKeyFor(SignatureAlgorithm.HS256);
        String encode= Encoders.BASE64.encode(secretKey.getEncoded());
        return encode;
    }

    /**
     * 检测token是否合法 并且返回claim 如果为null说明不合法
     * @param token
     * @return
     */
    public static Claims verify(String token){
        if(!StringUtils.hasLength(token)){
            return null;
        }
        JwtParser build=Jwts.parserBuilder().setSigningKey(keys).build();
        //如果验证失败会抛出异常 io.jsonwebtoken.ExpiredJwtException
        Claims claims=null;
        try{
            claims=build.parseClaimsJws(token).getBody();
        }catch (Exception e){
            log.error(ResultCode.FAILED_TOKEN.getMessage());
        }
        return claims;
    }

    /**
     * 获取token里的数据
     * @param jwtToken
     * @return
     */
    public static User getUserFromToken(String jwtToken) {
        Claims claims = verify(jwtToken);
        if (claims != null) {
            ObjectMapper objectMapper=SpringContextHolder.getBean(ObjectMapper.class);
            String userJson = claims.get(AppConfig.USER_SESSION, String.class); // 取出 JSON
            log.info("userJson  {}"+userJson);
            try {
                return objectMapper.readValue(userJson, User.class); // JSON → User
            } catch (JsonProcessingException e) {
                log.error("反序列化失败，JSON内容：{}", userJson, e);
                return null;
            }
        }
        return null;
    }
}